#include "AI.h"
#include "Player.h"
#include "Ally.h"

CAI::CAI()
{
}


CAI::~CAI()
{
}

void CAI::Update(float elapsedTime)
{
	switch (m_CurrState)
	{
	case IDLE_STATE:
		IdleState();
		break;
	case PATROL_STATE:
		PatrolState();
		break;
	case CHASE_STATE:
		ChaseState();
		break;
	case RETURN_STATE:
		ReturnState();
		break;
	case ATTACK_STATE:
		m_fAttackTimer -= elapsedTime;
		AttackState();
		break;
	}

	CAgent::Update(elapsedTime);
}

void CAI::IdleState()
{

}

void CAI::ReturnState()
{
	SGD::Vector vToHome = m_ptHomePos - m_ptPosition;

	if (vToHome.ComputeLength() <= 32)
	{
		m_ptPosition = m_ptHomePos;
		if (m_ptWayPoints.size() > 0)
			SwitchStates(PATROL_STATE);
		else
			SwitchStates(IDLE_STATE);
	}
	if (m_bPathFinding == false)
		m_vtVelocity = vToHome;
}

void CAI::PatrolState()
{
	if (m_nCurrWaypoint >= m_ptWayPoints.size())
	{
		if (m_bPathFinding == false)
			m_nCurrWaypoint = 0;
		else
			m_bPathFinding = false;
	}

	SGD::Vector vPatrol;
	vPatrol = m_ptWayPoints[m_nCurrWaypoint] - m_ptPosition; if (vPatrol.ComputeLength() <= 40)
		m_nCurrWaypoint++;

	if (m_bPathFinding == false)
		m_vtVelocity = vPatrol;
}

void CAI::ChaseState()
{
	if (m_tTable.Target != nullptr)
	{
		SGD::Point target = m_tTable.Target->GetPosition();
		SGD::Vector vToTarget = target - m_ptPosition;

		vToTarget.Normalize();

		vToTarget *= 128;

		if (vToTarget.x > 200)
			vToTarget.x = 200;
		if (vToTarget.y > 200)
			vToTarget.y = 200;

		if (vToTarget.ComputeLength() <= 40)
			m_bInRange = true;

		if (vToTarget.ComputeLength() >= 400 && target != m_ptHomePos)
			target = m_ptHomePos;

		if (m_bPathFinding == false)
			m_vtVelocity = vToTarget;
	}
}

void CAI::AttackState()
{
	if (m_fAttackTimer <= 0)
	{
		SGD::Event* attackPlayer = new SGD::Event("ATTACK_PLAYER", &m_fDamage, this);
		attackPlayer->QueueEvent(m_tTable.Target);
		m_fAttackTimer = m_fDefAttack;
	}

	if (SGD::Vector(m_tTable.Target->GetPosition() - m_ptPosition).ComputeLength() >= 40)
	{
		SwitchStates(CHASE_STATE);
		m_bInRange = false;
	}
}

/*virtual*/ void CAI::HandleCollision(const Entity* pOther) /*override*/
{
	if (pOther->GetType() == ENT_PHINT)
	{
		m_bPathFinding = true;
		SGD::Rectangle rIntersect = pOther->GetRect().ComputeIntersection(GetRect());
		if (rIntersect.ComputeHeight() <= rIntersect.ComputeWidth())
		{
#pragma region bottom
			if (GetRect().top == rIntersect.top)
			{
				m_ptPosition.y = pOther->GetPosition().y + pOther->GetSize().height;

				SGD::Point leftProject = { pOther->GetPosition().x - m_szSize.width - 5, m_ptPosition.y };

				if (m_tTable.Target->GetPosition().x + m_tTable.Target->GetSize().width < pOther->GetPosition().x)
				{
					SGD::Vector toLeft = leftProject - m_ptPosition;

					toLeft.Normalize();
					toLeft *= 128;

					m_vtVelocity = toLeft;
				}
				else
				{
					SGD::Point rightProject = { pOther->GetPosition().x + pOther->GetSize().width, m_ptPosition.y };

					if (m_tTable.Target->GetPosition().x > pOther->GetPosition().x + pOther->GetSize().width)
					{
						SGD::Vector toRight = rightProject - m_ptPosition;

						toRight.Normalize();
						toRight *= 128;

						m_vtVelocity = toRight;
					}
					else
					{
						if ((pOther->GetPosition().x + pOther->GetSize().width) - (m_tTable.Target->GetPosition().x + m_tTable.Target->GetSize().width) < m_tTable.Target->GetPosition().x - pOther->GetPosition().x)
						{
							m_ptWayPoints.push_back(rightProject);
							m_ptWayPoints.push_back({ rightProject.x, rightProject.y - pOther->GetSize().height - m_szSize.height });
						}
						else
						{
							m_ptWayPoints.push_back(leftProject);
							m_ptWayPoints.push_back({ leftProject.x, leftProject.y - pOther->GetSize().height - m_szSize.height });
						}
						SwitchStates(PATROL_STATE);
					}
				}
				m_ptPosition.y = pOther->GetPosition().y + pOther->GetSize().height;
			}
#pragma endregion

#pragma region top
			else
			{
				m_ptPosition.y = pOther->GetPosition().y - m_szSize.height;

				SGD::Point leftProject = { pOther->GetPosition().x - m_szSize.width - 5, m_ptPosition.y };

				if (m_tTable.Target->GetPosition().x + m_tTable.Target->GetSize().width < pOther->GetPosition().x)
				{
					SGD::Vector toLeft = leftProject - m_ptPosition;

					toLeft.Normalize();
					toLeft *= 128;

					m_vtVelocity = toLeft;
				}
				else
				{
					SGD::Point rightProject = { pOther->GetPosition().x + pOther->GetSize().width, m_ptPosition.y };

					if (m_tTable.Target->GetPosition().x > pOther->GetPosition().x + pOther->GetSize().width)
					{
						SGD::Vector toRight = rightProject - m_ptPosition;

						toRight.Normalize();
						toRight *= 128;

						m_vtVelocity = toRight;
					}
					else
					{
						if ((pOther->GetPosition().x + pOther->GetSize().width) - (m_tTable.Target->GetPosition().x + m_tTable.Target->GetSize().width) < m_tTable.Target->GetPosition().x - pOther->GetPosition().x)
						{
							m_ptWayPoints.push_back(rightProject);
							m_ptWayPoints.push_back({ rightProject.x, rightProject.y + pOther->GetSize().height + m_szSize.height });
						}
						else
						{
							m_ptWayPoints.push_back(leftProject);
							m_ptWayPoints.push_back({ leftProject.x, leftProject.y - pOther->GetSize().height - m_szSize.height });
						}
						SwitchStates(PATROL_STATE);
					}
				}
				m_ptPosition.y = pOther->GetPosition().y - m_szSize.height;
			}
#pragma endregion
		}

		else if (rIntersect.ComputeHeight() >= rIntersect.ComputeWidth())
		{
#pragma region right
			if (GetRect().left == rIntersect.left)
			{
				SGD::Point BotProject = { m_ptPosition.x, pOther->GetPosition().y - m_szSize.height - 5 };

				if (m_tTable.Target->GetPosition().y + m_tTable.Target->GetSize().height < pOther->GetPosition().y)
				{
					SGD::Vector toBot = BotProject - m_ptPosition;

					toBot.Normalize();
					toBot *= 128;

					m_vtVelocity = toBot;
				}
				else
				{
					SGD::Point TopProject = { pOther->GetPosition().x, m_ptPosition.y + pOther->GetPosition().y + pOther->GetSize().height + 5 };

					if (m_tTable.Target->GetPosition().y > pOther->GetPosition().y + pOther->GetSize().height)
					{
						SGD::Vector toTop = TopProject - m_ptPosition;

						toTop.Normalize();
						toTop *= 128;

						m_vtVelocity = toTop;
					}
					else
					{
						if ((pOther->GetPosition().y + pOther->GetSize().height) - (m_tTable.Target->GetPosition().y + m_tTable.Target->GetSize().height) < m_tTable.Target->GetPosition().y - pOther->GetPosition().y)
						{
							m_ptWayPoints.push_back(TopProject);
							m_ptWayPoints.push_back({ TopProject.x + pOther->GetSize().width + pOther->GetSize().width, TopProject.y });
						}
						else
						{
							m_ptWayPoints.push_back(BotProject);
							m_ptWayPoints.push_back({ BotProject.x + pOther->GetSize().width + pOther->GetSize().width, BotProject.y });
						}
						SwitchStates(PATROL_STATE);
					}
				}
			}
			m_ptPosition.x = pOther->GetPosition().x - m_szSize.width - 5;
		}
#pragma region

#pragma region left
		else
		{
			SGD::Point BotProject = { m_ptPosition.x, pOther->GetPosition().y - m_szSize.height - 5 };

			if (m_tTable.Target->GetPosition().y + m_tTable.Target->GetSize().height < pOther->GetPosition().y)
			{
				SGD::Vector toBot = BotProject - m_ptPosition;

				toBot.Normalize();
				toBot *= 128;

				m_vtVelocity = toBot;
			}
			else
			{
				SGD::Point TopProject = { pOther->GetPosition().x, m_ptPosition.y + pOther->GetPosition().y + pOther->GetSize().height + 5 };

				if (m_tTable.Target->GetPosition().y > pOther->GetPosition().y + pOther->GetSize().height)
				{
					SGD::Vector toTop = TopProject - m_ptPosition;

					toTop.Normalize();
					toTop *= 128;

					m_vtVelocity = toTop;
				}
				else
				{
					if ((pOther->GetPosition().y + pOther->GetSize().height) - (m_tTable.Target->GetPosition().y + m_tTable.Target->GetSize().height) < m_tTable.Target->GetPosition().y - pOther->GetPosition().y)
					{
						m_ptWayPoints.push_back(TopProject);
						m_ptWayPoints.push_back({ TopProject.x + pOther->GetSize().width + pOther->GetSize().width, TopProject.y });
					}
					else
					{
						m_ptWayPoints.push_back(BotProject);
						m_ptWayPoints.push_back({ BotProject.x + pOther->GetSize().width + pOther->GetSize().width, BotProject.y });
					}
					SwitchStates(PATROL_STATE);
				}
			}
		}
		m_ptPosition.x = pOther->GetPosition().x - m_szSize.width - 5;
#pragma endregion
	}
}
